package com.example.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.convert.SysDictConvert;
import com.example.demo.domain.base.PageResult;
import com.example.demo.domain.entity.SysDictDO;
import com.example.demo.domain.param.SysDictCreateParam;
import com.example.demo.domain.param.SysDictQueryParam;
import com.example.demo.domain.param.SysDictUpdateParam;
import com.example.demo.domain.vo.SysDictInfoVO;
import com.example.demo.domain.vo.SysDictTreeVO;
import com.example.demo.domain.vo.SysDictVO;
import com.example.demo.dao.SysDictMapper;
import com.example.demo.service.SysDictService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * SysDictServiceImpl
 *
 * @author haochen78
 * @date 2025/10/3 22:36
 **/
@Service
public class SysDictServiceImpl implements SysDictService {

    @Autowired
    private SysDictMapper sysDictMapper;

    @Override
    public boolean create(SysDictCreateParam param) {
        SysDictDO sysDictDO = SysDictConvert.INSTANCE.paramToDo(param);
        return sysDictMapper.insert(sysDictDO) > 0;
    }

    @Override
    public boolean update(SysDictUpdateParam param) {
        SysDictDO sysDictDO = SysDictConvert.INSTANCE.paramToDo(param);
        return sysDictMapper.updateById(sysDictDO) > 0;
    }

    @Override
    public boolean delete(Long id) {
        return sysDictMapper.deleteById(id) > 0;
    }

    @Override
    public SysDictVO getById(Long id) {
        return SysDictConvert.INSTANCE.doToVo(sysDictMapper.selectById(id));
    }

    @Override
    public PageResult<SysDictVO> list(SysDictQueryParam param) {
        LambdaQueryWrapper<SysDictDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(param.getTypeCode()), SysDictDO::getTypeCode, param.getTypeCode());
        wrapper.eq(StringUtils.isNotBlank(param.getCode()), SysDictDO::getCode, param.getCode());
        wrapper.eq(StringUtils.isNotBlank(param.getName()), SysDictDO::getName, param.getName());
        wrapper.eq(StringUtils.isNotBlank(param.getParentCode()), SysDictDO::getParentCode, param.getParentCode());
        wrapper.eq(Objects.nonNull(param.getStatus()), SysDictDO::getStatus, param.getStatus());
        Page<SysDictDO> page = sysDictMapper.selectPage(new Page<>(param.getPageNum(), param.getPageSize()), wrapper);
        Page<SysDictVO> pageInfo = SysDictConvert.INSTANCE.doToVoPage(page);
        return new PageResult<>(pageInfo);
    }

    @Override
    public List<SysDictInfoVO> getDictByType(String typeCode) {
        List<SysDictDO> sysDictList = sysDictMapper.selectList(new LambdaQueryWrapper<SysDictDO>().eq(SysDictDO::getTypeCode, typeCode).eq(SysDictDO::getStatus, 1).orderByAsc(SysDictDO::getSortOrder));
        return SysDictConvert.INSTANCE.doToVoList(sysDictList);
    }

    @Override
    public SysDictVO getDictByCode(String typeCode, String code) {
        LambdaQueryWrapper<SysDictDO> queryWrapper = new LambdaQueryWrapper<SysDictDO>().eq(SysDictDO::getTypeCode, typeCode).eq(SysDictDO::getCode, code).eq(SysDictDO::getStatus, 1).orderByAsc(SysDictDO::getSortOrder);
        SysDictDO sysDictList = sysDictMapper.selectOne(queryWrapper);
        return SysDictConvert.INSTANCE.doToVo(sysDictList);
    }

    @Override
    public List<SysDictTreeVO> buildDictTree(String typeCode) {
        SysDictConvert convert = SysDictConvert.INSTANCE;
        // 1. 从数据库查询所有需要的DO对象
        List<SysDictDO> allDictDOList = sysDictMapper.selectList(new LambdaQueryWrapper<SysDictDO>().eq(SysDictDO::getTypeCode, typeCode).eq(SysDictDO::getStatus, 1).orderByAsc(SysDictDO::getSortOrder));

        // 2. 一次性将所有DO转换为TreeVO，这是构建树的基础
        List<SysDictTreeVO> allTreeVOList = allDictDOList.stream().map(convert::toTreeVO).collect(Collectors.toList());

        // 3. 创建一个Map，用于通过code快速查找TreeVO，提高组装效率
        Map<String, SysDictTreeVO> treeVOMap = allTreeVOList.stream().collect(Collectors.toMap(SysDictTreeVO::getCode, treeVO -> treeVO));

        // 4. 遍历所有DO，根据parentCode信息，在TreeVO上构建父子关系
        List<SysDictTreeVO> rootList = new ArrayList<>();
        for (SysDictDO dictDO : allDictDOList) {
            String currentCode = dictDO.getCode();
            String parentCode = dictDO.getParentCode();

            // 从Map中获取当前节点对应的VO
            SysDictTreeVO currentTreeVO = treeVOMap.get(currentCode);

            if (parentCode == null || !treeVOMap.containsKey(parentCode)) {
                // 如果没有父节点，或者父节点不存在，则为根节点
                rootList.add(currentTreeVO);
            } else {
                // 如果有父节点，找到父节点VO并将当前VO加入其children列表
                SysDictTreeVO parentTreeVO = treeVOMap.get(parentCode);
                if (parentTreeVO.getChildren() == null) {
                    parentTreeVO.setChildren(new ArrayList<>());
                }
                parentTreeVO.getChildren().add(currentTreeVO);
            }
        }

        return rootList;
    }
}
